#include "vm.hpp"
#include "actor.hpp"
#include "exception.hpp"
#include <string>
#include <iostream>
#include <fstream>

using namespace std;
using namespace BMD;

int main(int argc, char* argv[])
{
  if (argc < 2)
  {
    cerr << "usage: " << argv[0] << " FILENAME" << endl
         << "       " << argv[0] << " FILENAME FUNCTION_NAME [ARGS]*" << endl;
    return 0;
  }
  
  // create an actor
  shared_ptr<Actor> actor(new Actor());
  
  string filename(argv[1]);
  
  try
  {
    actor->load_from_file(filename);
  }
  catch (instruction_parse_error e)
  {
    cerr << e.what() << endl
         << "Couldn't successfully parse " + filename << endl;
    return 1;
  }

  // if we're just given a filename, we 
  // can run the file
  if (argc == 2)
  {
    try
    {
      actor->run();
    }
    catch (runtime_error e)
    {
      cerr << "Runtime error occurred: " << endl
           << "\t" << e.what() << endl;      

      // print error info
      cerr << "Accumulator: " << actor->get_vm()->get_accumulator() << endl;
      cerr << "Call stack: " << endl;
      actor->get_vm()->print_call_stack();
      
      return 1;
    }
    return 0;
  }

  // grab the function name and any arguments
  string func_name(argv[2]);
  vector<Value> func_args;
  for (int i = 3; i < argc; ++i)
    func_args.push_back(Value::parse_value(argv[i]));
  
  // call the function and print the return value
  cout << "Calling " << func_name << "(";
  for (unsigned int i = 0; i < func_args.size(); ++i)
    cout << (i == 0 ? "" : ", ") << func_args[i];
  cout << ")" << endl;
  
  try
  {
    actor->call_function(func_name, func_args);
  }
  catch (runtime_error e)
  {
    cerr << "Runtime error occurred: " << endl
         << "\t" << e.what() << endl;
    return 1;
  }

  cout << func_name << " returned: " << actor->get_vm()->get_accumulator() << endl;
  return 0;
}
  
  
